package com.yesun.task.pipeline.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * AOP实现数据源动态切换，所有的写操作切换到master，所有的读操作切换到多个slave
 *
 * @author chunmingdeng
 */
@Component //必须加入ioc容器，AOP才能生效
@Aspect
@Slf4j
public class DataSourceAspectJ implements Ordered {

    //通过方法名称切入，自动拦截所有的services.impl中的方法；比使用注解指定更简单,
    @Pointcut(value = "execution(public * *..service.impl..*.*(..))")
    public void pointcut() {
    }

    /**
     * 必须使用Around才能够使用ProceedingJoinPoint
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("com.yesun.task.pipeline.config.DataSourceAspectJ.pointcut()")
    public Object changeDataSourceHold(ProceedingJoinPoint joinPoint) throws Throwable {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();

        //判断DB注解，如果标记了Clickhouse注解，表示走clickhouse，否则默认为Mysql
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
            //方法名相同
            if (method.getName().equals(methodName)) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                //参数名相同
                if (parameterTypes.length == arguments.length) {
                    ClickhouseDb db = method.getAnnotation(ClickhouseDb.class);
                    if(db != null) {
                        DBContextHolder.clickhouse();
                        return joinPoint.proceed();
                    }
                    break;
                }
            }
        }
        //默认为mysql
        DBContextHolder.mysql();
        return joinPoint.proceed();
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
